_Pragma("once");

#include <string>
#include <cstring>
#include <cstdio>
#include <memory>
#include <vector>
#include <algorithm>


using StringVector = std::vector<std::string>;
using StringVectorPtr = std::shared_ptr<StringVector>;

using StringViewVector = std::vector<std::string_view>;
using StringViewVectorPtr = std::shared_ptr<StringViewVector>;

using NetworkString = std::string;

using NetworkStringView = std::basic_string_view<NetworkString::value_type>;

namespace StringUtility {
extern const std::string EMPTY_STRING;

     extern const ssize_t MAX_BYTE_WIDTH;
     extern const ssize_t BATCH_FORMAT_COUNT;

#define BINARY_TO_CHAR(BIN) std::to_string((BIN)) //('0' + (BIN))


inline std::string& dumpMemory(const uint8_t* data, const size_t length, const char* format, std::string& output) {
    const size_t appendLength = length * MAX_BYTE_WIDTH;
    size_t offset = output.length();
    output.resize(offset + appendLength + 2);

    const size_t tailSize = length % BATCH_FORMAT_COUNT;
    int writeLength = 0;
    const uint8_t* pEndIterator = data + tailSize;
    char* pBuffer = &output[0] + offset;//attention
    const uint8_t* pTemp = nullptr;
    for (pTemp = data; pTemp < pEndIterator; ++pTemp) {
        writeLength = std::snprintf(pBuffer, MAX_BYTE_WIDTH + 1, format, *pTemp);
        if (writeLength > MAX_BYTE_WIDTH) {
            writeLength = MAX_BYTE_WIDTH;
        }
        pBuffer += writeLength;
    }

    if (length >= BATCH_FORMAT_COUNT) {
        size_t formatLength = std::strlen(format);
        char batchFormat[formatLength * BATCH_FORMAT_COUNT + 1];
        std::memcpy(batchFormat, format, formatLength);
        std::memcpy(batchFormat + formatLength, batchFormat, formatLength);//2
        formatLength <<= 1;
        std::memcpy(batchFormat + formatLength, batchFormat, formatLength);//4
        formatLength <<= 1;
        std::memcpy(batchFormat + formatLength, batchFormat, formatLength);//8
        batchFormat[sizeof (batchFormat) - 1] = '\0';
        pEndIterator = data + length;
        for (; pTemp < pEndIterator; pTemp += BATCH_FORMAT_COUNT) {
            writeLength = std::snprintf(pBuffer, MAX_BYTE_WIDTH * BATCH_FORMAT_COUNT + 1, batchFormat, pTemp[0], pTemp[1], pTemp[2], pTemp[3], pTemp[4], pTemp[5], pTemp[6], pTemp[7]);
            if (writeLength > MAX_BYTE_WIDTH * BATCH_FORMAT_COUNT) {
                writeLength = MAX_BYTE_WIDTH * BATCH_FORMAT_COUNT;
            }
            pBuffer += writeLength;
        }
    }

    output.resize(pBuffer - output.data());

    return output;
}

   inline StringVector::size_type indexOf(const StringVector& stringVector, const std::string& value){
        StringVector::const_iterator iterator = std::find(stringVector.cbegin(), stringVector.cend(), value);
        return std::distance(stringVector.cbegin(), iterator);
    }


    StringVector& split(const std::string& str, const std::string& splitter, StringVector& result);


    std::string& stringToBinary(const std::string& inputString, std::string& resultData);


};
